home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Modules / BackSpaceModules / Source / WorldSpace / WorldSpaceView.m < prev   
Text File  |  1994-05-23  |  6KB  |  310 lines

  1.  
  2. #import <appkit/appkit.h>
  3. #import "WorldSpaceView.h"
  4. #import "SpaceView.h"
  5. #import "Thinker.h"
  6.  
  7. @implementation WorldSpaceView
  8.  
  9. // x & y periods in milliseconds
  10. #define X_PERIOD 20000.0
  11. #define Y_PERIOD 19000.0
  12. #define DEFAULT_FPS 20
  13.  
  14. #define PI 3.1415926535
  15.  
  16. // #define MAX_IMAGE_WIDTH 200
  17. // #define MAX_IMAGE_HEIGHT 150
  18. #define MAX_IMAGE_WIDTH 256
  19. #define MAX_IMAGE_HEIGHT 256
  20.  
  21. #define MAX_X_SPEED (26)
  22. #define MAX_Y_SPEED (26)
  23.  
  24. #define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
  25. #define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
  26.  
  27.  
  28.  
  29. // move the world to its new position
  30. - oneStep
  31. {
  32.     NXRect black = {0,0,0,0};
  33.     NXRect ballRect;
  34.     BRECT new;
  35.     
  36.     then = now;
  37.     now = currentTimeInMs();
  38.     // now += 30;
  39.  
  40.     // calculate new ball x & y position
  41.     xpos = ((1 + sin(((float)now) / X_PERIOD * 2. * PI))/2.0) 
  42.         * maxCoord.x;
  43.     ypos = ((1 + sin(((float)now) / Y_PERIOD * 2. * PI))/2.0) 
  44.         * maxCoord.y;
  45.     
  46.     
  47.     if (xpos < (old.l - MAX_X_SPEED)) xpos = old.l - MAX_X_SPEED;
  48.     else if (xpos > (old.l + MAX_X_SPEED)) xpos = old.l + MAX_X_SPEED;
  49.  
  50.     if (ypos < (old.b - MAX_Y_SPEED)) ypos = old.b - MAX_Y_SPEED;
  51.     else if (ypos > (old.b + MAX_Y_SPEED)) ypos = old.b + MAX_Y_SPEED;
  52.  
  53.  
  54.     /* animate by selecting a new image to blit */
  55.  
  56.     [self incrementImageNumber];
  57.     
  58.     new.l = floor(xpos);
  59.     new.b = floor(ypos);
  60.     new.r = new.l + imageSize.width;
  61.     new.t = new.b + imageSize.height;
  62.     
  63.     ballRect.origin.x = 0;
  64.     ballRect.origin.y = 0;
  65.     ballRect.size.width = imageSize.width;
  66.     ballRect.size.height = imageSize.height;
  67.     
  68.     redrawTo.x = MIN(new.l, old.l);
  69.     redrawTo.y = MIN(new.b, old.b);
  70.  
  71.     redraw.origin.x = 0;
  72.     redraw.origin.y = 0;
  73.     redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
  74.     redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
  75.     
  76.     black.size= redraw.size;
  77.  
  78.     [buffer lockFocus];
  79.     PSsetgray(0);
  80.     NXRectFill(&black);
  81.     
  82.     ballTo.x = new.l - redrawTo.x;
  83.     ballTo.y = new.b - redrawTo.y;
  84.  
  85.     [currentImage composite:NX_SOVER fromRect:&ballRect toPoint:&ballTo];
  86.     [buffer unlockFocus];
  87.     
  88.     
  89.     // Now bring it onto the screen
  90.     
  91.     [buffer composite:NX_COPY fromRect:&redraw toPoint:&redrawTo];
  92.  
  93.     old = new;
  94.  
  95.     // now put in the stars...
  96.     
  97.     avoid.origin = redrawTo;
  98.     [mySpaceView setVoidRect:&avoid];
  99.     [mySpaceView oneStep];
  100.  
  101.     return self;
  102. }
  103.  
  104.  
  105.  
  106. static char *basename(char *path, const char *suffix)
  107. {
  108.     char *begin, *end, *name;
  109.     int len;
  110.     
  111.     if (strlen(path) < strlen(suffix)) {
  112.         end = begin = path;
  113.     }
  114.     else {
  115.     begin = rindex(path, '/');
  116.     if (begin) begin++;
  117.         else begin = path;
  118.     
  119.     end = path+strlen(path)-strlen(suffix);
  120.     if (0 != strcmp(end, suffix))
  121.         end = path+strlen(path);
  122.     
  123.     if (end < begin) end = begin;
  124.     }
  125.     len = end-begin;
  126.     name = malloc(len+1);
  127.     strncpy(name, begin, len);
  128.     name[len] = '\0';
  129.     return name;
  130. }
  131.  
  132.  
  133. static BOOL noAnimFile = FALSE;
  134.  
  135. - initFrame:(const NXRect *)frameRect
  136. {
  137.     char moduleDirectory[1024];
  138.     const char *animSpeed, *animFile, *animName;
  139.     char animFrame[1024];
  140.     int i, f;
  141.     id local_image;
  142.  
  143.     NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
  144.  
  145.     [super initFrame:frameRect];
  146.     [self allocateGState];        // For faster lock/unlockFocus
  147.     [self setClipping:NO];        // even faster...
  148.  
  149.     //in this case, I only need one buffer for several Views
  150.     if (!(buffer = [NXImage findImageNamed:"worldBuffer"]))
  151.     {
  152.         buffer = [[NXImage alloc] initSize:&black.size];
  153.         [buffer setName:"worldBuffer"];
  154.     }
  155.     
  156.     if ([buffer lockFocus])
  157.     {
  158.         PSsetgray(0);
  159.         NXRectFill(&black);
  160.         [buffer unlockFocus];
  161.     }
  162.  
  163.  
  164.     animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed");
  165.     if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS;
  166.     else framesPerSecond = atoi(animSpeed);
  167.  
  168.     animFile = NXGetDefaultValue([NXApp appName], "animFile");
  169.     if (animFile == NULL)
  170.     {
  171.         sprintf(moduleDirectory,"%s/Globe.anim",
  172.             [(BSThinker()) moduleDirectory:"WorldSpace"]);
  173.         animFile = moduleDirectory;
  174.     }
  175.     animName = basename((char *)animFile, ".anim");
  176.    
  177.     imageList = [[List alloc] init];
  178.  
  179.     /* construct the image list */
  180.     for (i=0; ; i++)
  181.     {
  182.         sprintf(animFrame, "%s/%s.%d.tiff", animFile, animName, i+1);
  183.         if (!(local_image = [NXImage findImageNamed:animFrame]))
  184.         {
  185.             if ((f=open(animFrame, O_RDONLY)) < 0) break;
  186.             close(f);
  187.  
  188.             local_image = [[NXImage alloc] initFromFile:animFrame];
  189.             if (local_image == NULL) break;    // never null, even if no file
  190.             [local_image setName:animFrame];
  191.         }
  192.  
  193.         [imageList addObject:local_image];
  194.         if (i == 0) [local_image getSize: &imageSize];
  195.     }
  196.     numberOfFrames = i;
  197.     currentFrame = 0;
  198.     
  199.     if (numberOfFrames == 0)
  200.     {
  201.         if (!noAnimFile)
  202.         NXRunAlertPanel([NXApp appName], "Could not open %s",
  203.                 NULL, NULL, NULL, animFile);
  204.         noAnimFile = TRUE;
  205.         return nil;
  206.     }
  207.  
  208.     nextRotationTime = 0;
  209.  
  210.     [self newViewSize];
  211.  
  212.     mySpaceView = [[SpaceView alloc] initFrame:frameRect];
  213.     avoid.size = imageSize;
  214.  
  215.     return self;
  216. }
  217.  
  218. - sizeTo:(NXCoord)width :(NXCoord)height
  219. {
  220.     [super sizeTo:width :height];
  221.     [mySpaceView sizeTo:width :height];
  222.     [self newViewSize];
  223.     return self;
  224. }
  225.  
  226. - drawSelf:(const NXRect *)rects :(int)rectCount
  227. {
  228.     // if (!rects || !rectCount) return self;
  229.     
  230.     //PSsetgray(0);
  231.     //NXRectFill(rects);
  232.     
  233.     //NXRectClip(rects);
  234.  
  235.     return self;
  236. }
  237.  
  238. - newViewSize
  239. {
  240.     //this is called every time View size changes
  241.     NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
  242.  
  243.     then = now = currentTimeInMs();
  244.  
  245.     if (oldSize.width == bounds.size.width &&
  246.             oldSize.height == bounds.size.height)
  247.         return self;
  248.     else
  249.     {
  250.         oldSize.width = bounds.size.width;
  251.         oldSize.height = bounds.size.height;
  252.     }
  253.     
  254.     maxCoord.x = bounds.size.width - imageSize.width;
  255.     maxCoord.y = bounds.size.height - imageSize.height;
  256.     if (maxCoord.x < 0) maxCoord.x = 0;
  257.     if (maxCoord.y < 0) maxCoord.y = 0;
  258.  
  259.  
  260.     old.l = old.r = maxCoord.x/2;
  261.     old.b = old.t = maxCoord.y/2;
  262.     ballTo.x = ballTo.y = 0;
  263.  
  264.     if ([buffer lockFocus])
  265.     {
  266.         PSsetgray(0);
  267.         NXRectFill(&black);
  268.         [buffer unlockFocus];
  269.     }
  270.  
  271.     return self;
  272. }
  273.  
  274. - incrementImageNumber
  275. {
  276.     if (now > nextRotationTime)
  277.     {
  278.         if (++currentFrame >= numberOfFrames) currentFrame = 0;
  279.         currentImage = [imageList objectAt:currentFrame];
  280.         nextRotationTime = now + 1000/framesPerSecond;
  281.     }
  282.  
  283.     return self;
  284. }
  285.  
  286. - (const char *)windowTitle
  287. {
  288.     return "World in Space";
  289. }
  290.  
  291. - didLockFocus
  292. {
  293.     [mySpaceView didLockFocus];
  294.     return self;
  295. }
  296.  
  297. - inspector:sender
  298. {
  299.     char buf[MAXPATHLEN];
  300.     
  301.     if (!sharedInspectorPanel)
  302.     {
  303.         [NXBundle getPath:buf forResource:"WorldSpace" ofType:"nib" inDirectory:[sender moduleDirectory:"WorldSpace"] withVersion:0];
  304.         [NXApp loadNibFile:buf owner:self withNames:NO];
  305.     }
  306.     return sharedInspectorPanel;
  307. }
  308.  
  309. @end
  310.